##### global settings #####

.PHONY: nemu entry testcase kernel run gdb test submit clean count count_
# .PHONY 声明伪目标，伪目标并不直接对应实际文件，而是表示一些任务或操作,此处我们在原有的基础上,添加count和count_命令

CC := gcc
# 定义编译器为 gcc

LD := ld
# 定义链接器为 ld

CFLAGS := -MMD -Wall -Werror -c
# 编译选项：
# -MMD: 生成依赖文件，用于自动管理文件依赖
# -Wall: 启用所有警告
# -Werror: 将警告视为错误
# -c: 只编译，不链接

LIB_COMMON_DIR := lib-common
# 定义库的通用目录路径

LIBC_INC_DIR := $(LIB_COMMON_DIR)/uclibc/include
# 定义 uclibc 的头文件路径

LIBC_LIB_DIR := $(LIB_COMMON_DIR)/uclibc/lib
# 定义 uclibc 的库文件路径

LIBC := $(LIBC_LIB_DIR)/libc.a
# 定义 uclibc 的库文件

FLOAT := obj/$(LIB_COMMON_DIR)/FLOAT/FLOAT.a
#定义浮点运算库（之前被注释掉了）,在PA2必做任务3中去掉注释

include config/Makefile.git
include config/Makefile.build
# 包含两个配置 Makefile 文件，这些文件可以定义项目的 git 设置和构建相关的通用规则

all: nemu
# 默认目标是 `nemu`，当用户直接执行 `make` 时，会执行这个目标

##### rules for building the project #####

include nemu/Makefile.part
include testcase/Makefile.part
include lib-common/FLOAT/Makefile.part
include kernel/Makefile.part
include game/Makefile.part
# 包含项目的各个部分的 Makefile，这些文件定义了各自的构建规则

nemu: $(nemu_BIN)
# 定义构建 `nemu` 的规则，依赖于变量 `$(nemu_BIN)`，`$(nemu_BIN)` 应该是在 `nemu/Makefile.part` 中定义的

testcase: $(testcase_BIN)
# 定义构建 `testcase` 的规则，依赖于变量 `$(testcase_BIN)`

kernel: $(kernel_BIN)
# 定义构建 `kernel` 的规则，依赖于变量 `$(kernel_BIN)`

game: $(game_BIN)
# 定义构建 `game` 的规则，依赖于变量 `$(game_BIN)`

##### rules for cleaning the project #####

clean-nemu:
	-rm -rf obj/nemu 2> /dev/null
# 删除 nemu 对应的构建输出目录

clean-testcase:
	-rm -rf obj/testcase 2> /dev/null
# 删除 testcase 对应的构建输出目录

clean-kernel:
	-rm -rf obj/kernel 2> /dev/null
# 删除 kernel 对应的构建输出目录

clean-game:
	-rm -rf obj/game 2> /dev/null
# 删除 game 对应的构建输出目录

clean: clean-cpp
	-rm -rf obj 2> /dev/null
	-rm -f *log.txt entry $(FLOAT) 2> /dev/null
# `clean` 目标调用 `clean-cpp`（这个目标应该在包含的 Makefile 中定义），然后删除 obj 目录，
# 删除日志文件和 entry 文件，以及浮点库（如果定义了 FLOAT）

##### some convinient rules #####

USERPROG := obj/testcase/matrix-mul-small
# 定义用户程序路径

#ENTRY := $(USERPROG)
# 将 ENTRY 定义为用户程序路径
ENTRY := $(kernel_BIN)

entry: $(ENTRY)
	objcopy -S -O binary $(ENTRY) entry
# `entry` 目标：使用 `objcopy` 将目标文件 $(ENTRY) 转换为二进制格式并保存为 `entry` 文件
# -S: 去除符号信息
# -O binary: 输出为二进制格式

run: $(nemu_BIN) $(USERPROG) entry
	$(call git_commit, "run")
	$(nemu_BIN) $(USERPROG)
# `run` 目标：先确保 nemu 二进制文件、用户程序和 entry 文件都已生成，
# 然后调用 `git_commit` 记录 "run" 提交，并执行 `$(nemu_BIN)`，传入 `$(USERPROG)` 作为参数

gdb: $(nemu_BIN) $(USERPROG) entry
	$(call git_commit, "gdb")
	gdb -s $(nemu_BIN) --args $(nemu_BIN) $(USERPROG)
# `gdb` 目标：确保必要的文件生成后，调用 `git_commit` 记录 "gdb" 提交，
# 然后使用 gdb 调试器启动 `$(nemu_BIN)`，并传入 `$(USERPROG)` 作为参数

test: $(nemu_BIN) $(testcase_BIN) entry
	$(call git_commit, "test")
	bash test.sh $(testcase_BIN)
# `test` 目标：确保所有必需的二进制文件生成后，调用 `git_commit` 记录 "test" 提交，
# 然后运行 `test.sh` 脚本，传入 `$(testcase_BIN)` 作为参数

submit: clean
	cd .. && zip -r $(STU_ID).zip $(shell pwd | grep -o '[^/]*$$')
# `submit` 目标：先调用 `clean` 进行清理，然后压缩当前目录为学号命名的 zip 文件，
# 该 zip 文件存储在上一级目录中

count:
	@echo "Counting lines of code (including empty lines)..."
	@find . -name '*.[ch]' | xargs wc -l

count_:
	@echo "Counting lines of code (excluding empty lines)..."
	@find . -name '*.[ch]' | xargs grep -v '^\s*$$' | wc -l
# count统计当前目录及其子目录中所有 `.c` 和 `.h` 文件的行数，包括空行
# count_统计当前目录及其子目录中所有 `.c` 和 `.h` 文件的行数，不包括空行(使用 grep -v '^\s*$$' 过滤掉空行，然后使用 wc -l 统计剩余行数)
